package com.heima.wemedia.service.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.constant.GlobalConstant;
import com.heima.common.constant.WeMediaConstant;
import com.heima.common.exception.CustomException;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.NewsAuthDto;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.dtos.WmNewsUpOrDownDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.utils.threadLocal.WmThreadLocalUtil;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.WmNewsAutoAuditService;
import com.heima.wemedia.service.WmNewsMaterialService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.service.WmNewsTaskService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.helper.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional
public class WmNewsServiceImpl  extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {
    @Autowired
    WmNewsMaterialMapper wmNewsMaterialMapper;
    @Autowired
    WmMaterialMapper wmMaterialMapper;
    @Autowired
    WmNewsMaterialService wmNewsMaterialService;
    @Autowired
    WmNewsAutoAuditService wmNewsAutoAuditService;
    @Autowired
    KafkaTemplate kafkaTemplate;
    @Autowired
    WmNewsTaskService wmNewsTaskService;
    @Override
    public ResponseResult findList(WmNewsPageReqDto dto) {
        //1.检查参数
        dto.checkParam();
        //2.条件查询
        //2.1用户id
        LambdaQueryWrapper<WmNews> lqw=new LambdaQueryWrapper<>();
        lqw.eq(WmNews::getUserId, WmThreadLocalUtil.getUserId())
        //2.2状态
                .eq(dto.getStatus()!=null,WmNews::getStatus,dto.getStatus())
        //2.3时间
                .between(dto.getBeginPubDate()!=null||dto.getEndPubDate()!=null,
                        WmNews::getPublishTime,dto.getBeginPubDate(),dto.getEndPubDate())
        //2.4关键字
                .like(dto.getKeyword()!=null,WmNews::getTitle,dto.getKeyword())
        //2.5频道
                .eq(dto.getChannelId()!=null,WmNews::getChannelId,dto.getChannelId())
        //2.6排序
                .orderByDesc(WmNews::getPublishTime);
        //2.5分页
        IPage page=new Page(dto.getPage(),dto.getSize());
        page = this.page(page, lqw);
        //3返回
        return ResponseResult.okResult(page);
    }

    @Override
    public ResponseResult submitNews(WmNewsDto dto) {
        //1.参数的检验
        if(dto==null|| StringUtils.isBlank(dto.getContent()))
        {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNews wmNews = new WmNews();
        //2.beanCopy
        BeanUtils.copyProperties(dto,wmNews);
        if(dto.getImages()!=null&&!dto.getImages().isEmpty())
        {
            wmNews.setImages(StringUtil.join(dto.getImages(),","));
        }
        //3.解析内容中的图片
        List<String> images=parsePicture(wmNews.getContent());
        //4.是否为自动
        //4.1是-处理图片
        if(wmNews.getType().equals(WmNews.Type.AUTO.getValue()))
        {
            List<String> cover=images;
            if(images.isEmpty())
            {
                wmNews.setType(WmNews.Type.NO_FIGURE.getValue());
            }
            else if(images.size()<3)
            {
                wmNews.setType(WmNews.Type.ONE_FIGURE.getValue());
                cover=images.stream().limit(1).collect(Collectors.toList());
            }
            else {
                wmNews.setType(WmNews.Type.MUL_FIGURE.getValue());
                cover=images.stream().limit(3).collect(Collectors.toList());
            }
            dto.setImages(cover);
            wmNews.setImages(StringUtil.join(cover,","));
        }
        //5.保存或更新
        saveOrUpdateWmNews(wmNews);
        //6.是否为草稿
        //6.1是-结束
        if(wmNews.getStatus().equals(WmNews.Status.NORMAL))
        {
            return ResponseResult.okResult();
        }
        //6.2不是-保存素材和文章的关系
        //6.2.1封面和文章的关系
        saveRelativeImages(dto.getImages(),wmNews, WeMediaConstant.WM_COVER_REFERENCE);
        //6.2.2内容和文章的关系
        saveRelativeImages(images,wmNews, WeMediaConstant.WM_CONTENT_REFERENCE);
        wmNewsAutoAuditService.autoAuditNews(wmNews.getId());
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult getInfoById(Integer wmNewsId) {
        if(wmNewsId==null)
        {
            throw new CustomException(AppHttpCodeEnum.PARAMS_NOT_NULL);
        }
        WmNews news = this.getById(wmNewsId);
        if(news==null)
        {
            throw new CustomException(AppHttpCodeEnum.NEWS_NOT_EXIST);
        }
        return ResponseResult.okResult(news);
    }

    @Override
    public ResponseResult deleteNewsAndMaterialRelationById(Integer wmNewsId) {
        if(wmNewsId==null)
        {
            throw new CustomException(AppHttpCodeEnum.NEWS_ID_NOT_EXIST);
        }
        WmNews news = this.getById(wmNewsId);
        if(news==null)
        {
            throw new CustomException(AppHttpCodeEnum.NEWS_NOT_EXIST);
        }
        if(news.getStatus().equals(WmNews.Status.PUBLISHED.getCode()))
        {
            throw new CustomException(AppHttpCodeEnum.NEWS_PUBLISHED);
        }
        wmNewsMaterialService.remove(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId,wmNewsId));
        this.removeById(wmNewsId);
        return ResponseResult.okResult();
    }

    private void saveRelativeImages(List<String> images,WmNews wmNews,Short type)
    {
        Set<String> set=new HashSet<>(images);
        List<WmNewsMaterial> collect = set.stream().map(url -> {
            WmMaterial material = wmMaterialMapper.selectOne(Wrappers.<WmMaterial>lambdaQuery().eq(WmMaterial::getUrl, url));
            if (material == null) {
                throw new CustomException(AppHttpCodeEnum.MATERIAL_EXPIRED);
            }
            WmNewsMaterial wmNewsMaterial = new WmNewsMaterial();
            wmNewsMaterial.setMaterialId(material.getId());
            wmNewsMaterial.setType(type);
            wmNewsMaterial.setNewsId(wmNews.getId());
            return wmNewsMaterial;
        }).collect(Collectors.toList());
        wmNewsMaterialService.saveBatch(collect);
    }

    public List<String> parsePicture(String content) {
        List<Map> maps = JSON.parseArray(content, Map.class);
        List<String> list=new ArrayList<>();
        for (Map map : maps) {
            if(map.get(GlobalConstant.TYPE_TAG).equals(GlobalConstant.IMAGE_TAG))
            {
                list.add((String) map.get(GlobalConstant.VALUE_TAG));
            }
        }
        return list;
    }

    @Override
    public void updateStatusAndReason(Integer id, WmNews.Status status, String reason) {
        if(id==null)
        {
            throw new RuntimeException(AppHttpCodeEnum.PARAMS_NOT_NULL.getErrorMessage());
        }
        WmNews wmNews = new WmNews();
        wmNews.setId(id);
        wmNews.setStatus(status.getCode());
        wmNews.setReason(reason);
        this.updateById(wmNews);
    }

    @Override
    public void updateStatusAndReasonAndArticleId(Integer id, WmNews.Status status, String reason, Long articleId) {
        if(id==null)
        {
            throw new RuntimeException(AppHttpCodeEnum.PARAMS_NOT_NULL.getErrorMessage());
        }
        WmNews wmNews = new WmNews();
        wmNews.setId(id);
        wmNews.setStatus(status.getCode());
        wmNews.setReason(reason);
        wmNews.setArticleId(articleId);
        this.updateById(wmNews);
    }

    @Override
    public ResponseResult downOrUp(WmNewsUpOrDownDto dto) {
        if(dto==null||dto.getId()==null||dto.getEnable()==null)
        {
            throw new CustomException(AppHttpCodeEnum.PARAMS_NOT_NULL);
        }
        if(!dto.getEnable().equals(WmNews.Enable.ENABLE.getValue())&&!dto.getEnable().equals(WmNews.Enable.NO_ENABLE.getValue()))
        {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNews news = this.getById(dto.getId());
        if(news==null)
        {
            throw new CustomException(AppHttpCodeEnum.NEWS_NOT_EXIST);
        }
        if (!news.getStatus().equals(WmNews.Status.PUBLISHED.getCode()))
        {
            throw new CustomException(AppHttpCodeEnum.STATUS_NOT_ALLOW);
        }
        news.setEnable(dto.getEnable());
        this.updateById(news);
        if(news.getArticleId()!=null)
        {
            Map<String,Object> map=new HashMap<>();
            map.put(GlobalConstant.ARTICLE_ID_TAG,news.getArticleId());
            map.put(GlobalConstant.ENABLE_TAG,dto.getEnable());
            kafkaTemplate.send(GlobalConstant.UP_OR_DOWN_TOPIC,JSON.toJSONString(map));
            log.info("发送消息成功->"+map);
        }
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult pageQuery(NewsAuthDto dto) {
        if (dto==null)
        {
            throw new CustomException(AppHttpCodeEnum.PARAMS_NOT_NULL);
        }
        dto.checkParam();
        if(dto.getStatus()!=null&&!WmNews.Status.check(dto.getStatus()))
        {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        LambdaQueryWrapper<WmNews> lqw=new LambdaQueryWrapper<>();
        lqw.like(StringUtils.isNotBlank(dto.getTitle()),WmNews::getTitle,dto.getTitle());
        if (dto.getStatus()!=null)
        {
            lqw.eq(WmNews::getStatus,dto.getStatus().shortValue());
        }
        IPage page=new Page(dto.getPage(),dto.getSize());
        page = this.page(page, lqw);
        return ResponseResult.okResult(page);
    }

    @Override
    public ResponseResult getNewsById(Integer id) {
        if (id==null)
        {
            throw new CustomException(AppHttpCodeEnum.NEWS_ID_NOT_EXIST);
        }
        WmNews news = this.getById(id);
        return news!=null?ResponseResult.okResult(news):ResponseResult.errorResult(AppHttpCodeEnum.NEWS_NOT_EXIST);
    }

    @Override
    public ResponseResult authFail(NewsAuthDto dto) {
        if (dto==null)
        {
            throw new CustomException(AppHttpCodeEnum.PARAMS_NOT_NULL);
        }
        if (dto.getId()==null)
        {
            throw new CustomException(AppHttpCodeEnum.NEWS_ID_NOT_EXIST);
        }
        boolean b = this.update(
                Wrappers.<WmNews>lambdaUpdate()
                        .eq(WmNews::getId, dto.getId())
                        .set(WmNews::getStatus, WmNews.Status.FAIL.getCode())
                        .set(WmNews::getReason, dto.getMsg())
        );
        return b?ResponseResult.okResult(AppHttpCodeEnum.SUCCESS):ResponseResult.errorResult(AppHttpCodeEnum.FAIL);
    }

    @Override
    public ResponseResult authPass(NewsAuthDto dto) {
        if (dto==null)
        {
            throw new CustomException(AppHttpCodeEnum.PARAMS_NOT_NULL);
        }
        if (dto.getId()==null)
        {
            throw new CustomException(AppHttpCodeEnum.NEWS_ID_NOT_EXIST);
        }
        boolean b = this.update(
                Wrappers.<WmNews>lambdaUpdate()
                        .eq(WmNews::getId, dto.getId())
                        .set(WmNews::getStatus, WmNews.Status.ADMIN_SUCCESS.getCode())
        );
        if (b)
        {
            WmNews news = this.getById(dto.getId());
            wmNewsTaskService.addNewsToTask(news.getId(),news.getPublishTime());
        }
        return b?ResponseResult.okResult(AppHttpCodeEnum.SUCCESS):ResponseResult.errorResult(AppHttpCodeEnum.FAIL);
    }

    private void saveOrUpdateWmNews(WmNews wmNews) {
        wmNews.setCreatedTime(new Date());
        wmNews.setSubmitedTime(new Date());
        wmNews.setEnable(WmNews.Enable.ENABLE.getValue());
        if(wmNews.getId()==null)
        {
            wmNews.setUserId(WmThreadLocalUtil.getUserId());
            log.warn(wmNews.toString());
            this.save(wmNews);
        }
        else{
            wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId,wmNews.getId()));
            this.updateById(wmNews);
        }
    }
}
